<?php

namespace App\Http\Controllers\Admin;

use App\Enums\AvailableStatus;
use App\Exports\ConvertRecordExport;
use App\Http\Controllers\Controller;
use App\Models\AgentUser;
use App\Models\ConvertDemand;
use App\Models\ConvertFormula;
use App\Models\ConvertRecord;
use App\Models\Product;
use Illuminate\Support\Arr;
use Vinlon\Laravel\LayAdmin\Exceptions\AdminException;

class ConvertController extends Controller
{
    /** 查询合成公式列表 */
    public function listFormulas()
    {
        /** @var AgentUser $user */
        $user = auth()->user();

        $query = ConvertFormula::query()
//            ->where('agent_id', $user->agent_id)
            ->with(['demands.product', 'target', 'agent'])
            ->withCount(['records'])
            ->when(request()->agent_id, function ($q) {
                return $q->where('agent_id', request()->agent_id);
            })
            ->orderByDesc('id');

        return paginate_result($query);
    }

    /** 查询公式详情 */
    public function getFormula($id)
    {
        return ConvertFormula::query()
            ->with(['demands'])
            ->find($id);
    }

    /** 保存合成公式 */
    public function saveFormula()
    {
        request()->validate([
            'name' => 'required',
            'start_time' => 'nullable',
            'end_time' => 'nullable',
            'limit' => 'required',
            'target_product_id' => 'required',
            'demand_product_ids' => 'required | array',
            'demand_quantities' => 'required | array',
        ]);
        $targetProductId = request()->target_product_id;
        $demandProductIds = request()->demand_product_ids ?: [];
        if (count($demandProductIds) != count(array_unique($demandProductIds))) {
            throw new AdminException('合成所需商品不能重复');
        }
        if (in_array($targetProductId, $demandProductIds)) {
            throw new AdminException('合成所需商品不能包含目标商品');
        }
        $products = Product::query()->whereIn('id', array_merge([$targetProductId], $demandProductIds))
            ->withCount(['available_tokens'])
            ->get()
            ->mapWithKeys(function (Product $product) {
                return [$product->id => $product];
            });

        /** @var Product $targetProduct */
        $targetProduct = Arr::pull($products, $targetProductId);
        if (!$targetProduct) {
            throw new AdminException('无效的目标商品');
        }
        if ($targetProduct->available_tokens_count <= 0) {
            throw new AdminException('目标商品没有库存');
        }

        $demandQuantities = request()->demand_quantities ?: [];
        $demandProductQuantity = [];
        foreach ($demandProductIds as $index => $productId) {
            if (!Arr::has($products, $productId)) {
                throw new AdminException('无效的商品');
            }
            $quantity = Arr::get($demandQuantities, $index);
            if (!$quantity) {
                throw new AdminException('合成所需数量不能为空');
            }
            $demandProductQuantity[$productId] = $quantity;
        }

        if (request()->id) {
            $formula = $this->findConvertFormulaOrFail(request()->id);
            // 删除原有的合成需求
            $formula->demands()->delete();
        } else {
            $formula = new ConvertFormula();
        }

        /** @var AgentUser $user */
        $user = auth()->user();
        $formula->agent_id = $user->agent_id;
        $formula->name = request()->name;
        $formula->target_product_id = request()->target_product_id;
        $formula->start_time = request()->start_time;
        $formula->end_time = request()->end_time;
        $formula->limit = request()->limit ?: -1;
        $formula->save();

        foreach ($demandProductQuantity as $productId => $quantity) {
            /** @var Product $product */
            $product = Arr::get($products, $productId);
            $demand = new ConvertDemand();
            $demand->convert_formula_id = $formula->id;
            $demand->product_id = $productId;
            $demand->contract_address = $product->contract_address;
            $demand->quantity = $quantity;
            $demand->save();
        }
    }

    /** 修改状态 */
    public function changeStatus($id)
    {
        request()->validate([
            'status' => 'required | enum_value:' . AvailableStatus::class,
        ]);
        $formula = $this->findConvertFormulaOrFail($id);
        $formula->status = request()->status;
        $formula->save();
    }

    /** 查询合成记录 */
    public function listRecords($formulaId)
    {
        $query = ConvertRecord::query()
            ->where('convert_formula_id', $formulaId)
            ->with(['user.auth']);

        return paginate_result($query);
    }

    /**
     * 合成记录导出.
     *
     * @param $formulaId
     */
    public function exportRecords($formulaId): ConvertRecordExport
    {
        $query = ConvertRecord::query()
            ->where('convert_formula_id', $formulaId)
            ->with(['user.auth'])
            ->get()
        ;

        /** @var ConvertFormula $formula */
        $formula = ConvertFormula::query()->find($formulaId);

        return new ConvertRecordExport($formula->name, $query->toArray());
    }

    private function findConvertFormulaOrFail($id)
    {
        /** @var AgentUser $user */
        $user = auth()->user();
        $formula = ConvertFormula::query()
            ->where('agent_id', $user->agent_id)
            ->find($id);
        if (!$formula) {
            throw new AdminException('无效的合成公式ID');
        }

        return $formula;
    }
}
